home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2005 June (DVD) / DPPRO0605DVD.iso / Install / program files / Borland / BDS / 3.0 / Demos / Delphi.Net / CLR / CDSBrowser / PetrVones.Utils.DataPacket.pas < prev   
Encoding:
Pascal/Delphi Source File  |  2004-10-22  |  10.1 KB  |  316 lines

  1. unit PetrVones.Utils.DataPacket;
  2.  
  3. interface
  4.  
  5. uses
  6.   System.Data, System.IO, System.Text, System.Xml;
  7.  
  8. type
  9.   EDataPacketError = class(System.Data.DataException);
  10.  
  11. procedure FillDataSet(DS: DataSet; DatPacketReader: TextReader); overload;
  12. procedure FillDataSet(DS: DataSet; DatPacket: string); overload;
  13.  
  14. implementation
  15.  
  16. resourcestring
  17.   RsElelementNotFound = 'Expected element {0} not found';
  18.   RsInvalidFieldType  = 'Invalid field type "{0}"';
  19.  
  20. type
  21.   TDataPacketElement = (peDataPacket, peMetadata, peFields, peField, peRowData);
  22.   TDataPacketConversion = (coNone, coDate, coDateTime, coTime, coBoolean);
  23.  
  24. const
  25.   DataPacketElementNames: array [TDataPacketElement] of string = ('DATAPACKET', 'METADATA', 'FIELDS', 'FIELD', 'ROWDATA');
  26.  
  27. type
  28.   TDataPacketDataColumn = class(DataColumn)
  29.   private
  30.     FDataPacketConversion: TDataPacketConversion;
  31.   protected
  32.     property DataPacketConversion: TDataPacketConversion read FDataPacketConversion write FDataPacketConversion;
  33.   end;
  34.  
  35. type
  36.   TDataPacketXmlReader = class(XmlTextReader)
  37.   private
  38.     FCurrentTable: DataTable;
  39.     FDescription: DataSet;
  40.   public
  41.     function get_Value: string; override;
  42.     function Read: Boolean; override;
  43.     property Description: DataSet read FDescription write FDescription;
  44.   end;
  45.  
  46. { TDataPacketXmlReader }
  47.  
  48. function TDataPacketXmlReader.get_Value: string;
  49. var
  50.   Column: TDataPacketDataColumn;
  51. begin
  52.   Result := inherited get_Value;
  53.   case NodeType of
  54.     XmlNodeType.Attribute:
  55.       begin
  56.         if Assigned(FCurrentTable) then
  57.           Column := TDataPacketDataColumn(FCurrentTable.Columns[Name])
  58.         else
  59.           Column := nil;  
  60.         if Assigned(Column) and (Column.ColumnMapping <> MappingType.Hidden) then
  61.           case Column.DataPacketConversion of
  62.             coTime:
  63.               Insert('.', Result, 9);
  64.             coDate, coDateTime:
  65.               if (Result.Length = 20) and (Result[9] = 'T') and (Result[12] = ':') then
  66.               begin
  67.                 Insert('-', Result, 5);
  68.                 Insert('-', Result, 8);
  69.                 Delete(Result, 20, 3);
  70.               end
  71.               else
  72.               if Result.Length = 8 then
  73.               begin
  74.                 Insert('-', Result, 5);
  75.                 Insert('-', Result, 8);
  76.               end;
  77.             coBoolean:
  78.               Result := Result.ToLower;
  79.          end;
  80.       end;
  81.    end;
  82. end;
  83.  
  84. function TDataPacketXmlReader.Read: Boolean;
  85. begin
  86.   Result := inherited Read;
  87.   if Result and (NodeType = XmlNodeType.Element) and HasAttributes then
  88.     FCurrentTable := Description.Tables[Name];
  89. end;
  90.  
  91. { FillDataSet }
  92.  
  93. procedure LoadDataPacket(DS: DataSet; Reader: XmlReader);
  94. const
  95.   RootTableName = 'ROW';
  96. var
  97.   ElementName: string;
  98.   ExpectingElement: TDataPacketElement;
  99.  
  100.   procedure CheckElementName(Element: TDataPacketElement);
  101.   begin
  102.     if DataPacketElementNames[Element] <> ElementName then
  103.       raise EDataPacketError.Create(System.String.Format(RsElelementNotFound, [ElementName]));
  104.   end;
  105.  
  106.   function CreateIdColumn(Table, NameTable: DataTable): DataColumn;
  107.   var
  108.     IdColumnName: string;
  109.   begin
  110.     IdColumnName := NameTable.TableName + '_IdNestedRel';
  111.     Result := Table.Columns[IdColumnName];
  112.     if not Assigned(Result) then
  113.     begin
  114.       Result := Table.Columns.Add(IdColumnName);
  115.       Result.DataType := typeof(System.Int32);
  116.       Result.ColumnMapping := MappingType.Hidden;
  117.     end;
  118.   end;
  119.  
  120.   procedure InvalidFieldType(FieldType: string);
  121.   begin
  122.     raise EDataPacketError.Create(System.String.Format(RsInvalidFieldType, [FieldType]));
  123.   end;
  124.  
  125.   procedure ReadFields(CurrentTable: DataTable);
  126.   type
  127.     TDataColumn_Array = array of DataColumn;
  128.   var
  129.     AttrName, AttrNameValue, FieldTypeValue, SubTypeValue: string;
  130.     Column: TDataPacketDataColumn;
  131.     ParentIdColumn, ChildIdColumn: DataColumn;
  132.     NestedTable: DataTable;
  133.     NestedRelation: DataRelation;
  134.     RelationName: string;
  135.   begin
  136.     while Reader.Read do
  137.       case Reader.NodeType of
  138.         XmlNodeType.Element:
  139.           if Reader.Name = DataPacketElementNames[peField] then
  140.           begin
  141.             AttrName := '';
  142.             FieldTypeValue := '';
  143.             SubTypeValue := '';
  144.             while Reader.MoveToNextAttribute do
  145.             begin
  146.               AttrName := Reader.Name.ToLower;
  147.               if AttrName = 'attrname' then
  148.                 AttrNameValue := Reader.Value
  149.               else
  150.               if AttrName = 'fieldtype' then
  151.                 FieldTypeValue := Reader.Value
  152.               else
  153.               if AttrName = 'subtype' then
  154.                 SubTypeValue := Reader.Value;
  155.             end;
  156.             if FieldTypeValue = 'nested' then
  157.             begin
  158.               ParentIdColumn := CreateIdColumn(CurrentTable, CurrentTable);
  159.               ParentIdColumn.AllowDBNull := False;
  160.               ParentIdColumn.AutoIncrement := True;
  161.               ParentIdColumn.Unique := True;
  162.               CurrentTable.PrimaryKey := TDataColumn_Array.Create(ParentIdColumn);
  163.               NestedTable := DS.Tables.Add(CurrentTable.TableName + AttrNameValue);
  164.               ChildIdColumn := CreateIdColumn(NestedTable, CurrentTable);
  165.               RelationName := CurrentTable.TableName + '_' + NestedTable.TableName;
  166.               NestedRelation := DS.Relations.Add(RelationName, ParentIdColumn, ChildIdColumn, True);
  167.               NestedRelation.Nested := True;
  168.               ReadFields(NestedTable);
  169.             end
  170.             else
  171.             begin
  172.               Column := TDataPacketDataColumn.Create;
  173.               Column.DataPacketConversion := coNone;
  174.               Column.ColumnName := AttrNameValue;
  175.               Column.ColumnMapping := MappingType.Attribute;
  176.               Column.Caption := AttrNameValue;
  177.               if FieldTypeValue = 'fixed' then
  178.                 Column.DataType := typeof(System.Decimal)
  179.               else
  180.               if FieldTypeValue = 'boolean' then
  181.               begin
  182.                 Column.DataType := typeof(System.Boolean);
  183.                 Column.DataPacketConversion := coBoolean;
  184.               end
  185.               else
  186.               if FieldTypeValue = 'r8' then
  187.                 Column.DataType := typeof(System.Double)
  188.               else
  189.               if FieldTypeValue = 'date' then
  190.               begin
  191.                 Column.DataType := typeof(System.DateTime);
  192.                 Column.DataPacketConversion := coDate;
  193.               end
  194.               else
  195.               if FieldTypeValue = 'dateTime' then
  196.               begin
  197.                 Column.DataType := typeof(System.DateTime);
  198.                 Column.DataPacketConversion := coDateTime;
  199.               end
  200.               else
  201.               if FieldTypeValue = 'i4' then
  202.                 Column.DataType := typeof(System.Int32)
  203.               else
  204.               if FieldTypeValue = 'i8' then
  205.                 Column.DataType := typeof(System.Int64)
  206.               else
  207.               if FieldTypeValue = 'i2' then
  208.                 Column.DataType := typeof(System.Int16)
  209.               else
  210.               if FieldTypeValue = 'string' then
  211.                 Column.DataType := typeof(System.String)
  212.               else
  213.               if FieldTypeValue = 'time' then
  214.               begin
  215.                 Column.DataType := typeof(System.DateTime);
  216.                 Column.DataPacketConversion := coTime;
  217.               end
  218.               else
  219.               if FieldTypeValue = 'string.uni' then
  220.                 Column.DataType := typeof(System.String)
  221.               else
  222.               if FieldTypeValue = 'ui2' then
  223.                 Column.DataType := typeof(System.UInt16)
  224.               else
  225.               if FieldTypeValue = 'ui4' then
  226.                 Column.DataType := typeof(System.UInt32)
  227.               else
  228.               if FieldTypeValue = 'bin.hex' then
  229.               begin
  230.                 if SubTypeValue = 'Text' then
  231.                   Column.DataType := typeof(System.String)
  232.                 else
  233.                 if (SubTypeValue = 'Graphics') or (SubTypeValue = 'TypedBinary') then
  234.                   Column.DataType := typeof(TBytes)
  235.                 else
  236.                   InvalidFieldType(System.String.Format('{0}/{1}', [FieldTypeValue, SubTypeValue]));
  237.               end
  238.               else
  239.                 InvalidFieldType(FieldTypeValue);
  240.               CurrentTable.Columns.Add(Column);
  241.             end;
  242.           end;
  243.         XmlNodeType.EndElement:
  244.           if Reader.Name = DataPacketElementNames[peFields] then
  245.             Break;
  246.       end;
  247.   end;
  248.  
  249.   procedure ReadData;
  250.   begin
  251.     DS.ReadXml(Reader, XmlReadMode.IgnoreSchema);
  252.   end;
  253.  
  254. begin
  255.   ExpectingElement := peDataPacket;
  256.   while Reader.Read do
  257.     case Reader.NodeType of
  258.       XmlNodeType.Element:
  259.         begin
  260.           ElementName := Reader.Name;
  261.           case ExpectingElement of
  262.             peDataPacket:
  263.               begin
  264.                 CheckElementName(peDataPacket);
  265.                 ExpectingElement := peMetadata;
  266.               end;
  267.             peMetadata:
  268.               begin
  269.                 CheckElementName(peMetadata);
  270.                 ExpectingElement := peFields;
  271.               end;
  272.             peFields:
  273.               begin
  274.                 ReadFields(DS.Tables.Add(RootTableName));
  275.                 ExpectingElement := peRowData;
  276.                 Reader.Skip;
  277.               end;
  278.             peRowData:
  279.               if ElementName = DataPacketElementNames[peRowData] then
  280.               begin
  281.                 ReadData;
  282.                 Break;
  283.               end;  
  284.           end;
  285.         end;
  286.     end;
  287. end;
  288.  
  289. procedure FillDataSet(DS: DataSet; DatPacketReader: TextReader);
  290. var
  291.   Reader: TDataPacketXmlReader;
  292. begin
  293.   DS.Reset;
  294.   Reader := TDataPacketXmlReader.Create(DatPacketReader);
  295.   try
  296.     Reader.Description := DS;
  297.     LoadDataPacket(DS, Reader);
  298.   finally
  299.     Reader.Close;
  300.   end;  
  301. end;
  302.  
  303. procedure FillDataSet(DS: DataSet; DatPacket: string);
  304. var
  305.   Reader: StringReader;
  306. begin
  307.   Reader := StringReader.Create(DatPacket);
  308.   try
  309.     FillDataSet(DS, Reader);
  310.   finally
  311.     Reader.Close;
  312.   end;
  313. end;
  314.  
  315. end.
  316.